package com.hjj.web.core;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author: luoyajun
 * @date: 2020/4/23 19:43
 */
@Slf4j
@Service
public class QuartzService {

    @Autowired
    @Qualifier("scheduler")
    private Scheduler scheduler;

    /**
     * 默认任务组名称
     */
    private static String JOB_GROUP_NAME = "WEBSOCKET_JOB_GROUP";

    /**
     * 添加执行一次的任务
     *
     * @param jobName      任务名称
     * @param jobGroupName 任务组
     * @param delay        执行延迟
     * @param timeUnit     执行延迟单位
     * @param cls          job类
     * @param description  任务描述
     * @return true添加成功/false添加失败
     */
    public boolean schedule(String jobName, String jobGroupName, long delay, TimeUnit timeUnit,
                            Class<? extends Job> cls, String description, JobDataMap jobDataMap) {

         JobBuilder jobBuilder = JobBuilder.newJob(cls).withIdentity(jobName, jobGroupName)
                .withDescription(description);

        if (jobDataMap != null && !jobDataMap.isEmpty()) {
            jobBuilder.setJobData(jobDataMap);
        }

        JobDetail jobDetail = jobBuilder.build();

        long executeTime = System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(delay, timeUnit);

        Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                .startAt(new Date(executeTime)).build();

        try {
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            log.error("创建任务失败,失败原因:{}", ExceptionUtils.getStackTrace(e));
            return false;
        }
        return true;
    }

    /**
     * 创建一个定时任务
     *
     * @param jobName        任务名称
     * @param jobGroupName   任务组名称
     * @param cronExpression cron表达式
     * @param description    任务描述
     * @return
     */
    public Boolean addJob(String jobName, String jobGroupName, String cronExpression, Class cls, String description) {
        if (!CronExpression.isValidExpression(cronExpression)) {
            return false;
        }
        // 构建job信息
        JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, jobGroupName)
                .withDescription(description).build();

        // 表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

        // 按照cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                .startNow().withSchedule(scheduleBuilder).build();

        try {
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            log.error("创建任务失败,失败原因:{}", ExceptionUtils.getStackTrace(e));
            return false;
        }
        return true;
    }

    public Boolean addJob(String jobName, String cronExpression, Class cls, String description) {
        return addJob(jobName, cronExpression, cls, description, null);
    }

    /**
     * 创建一个定时任务
     *
     * @param jobName        任务名称
     * @param cronExpression cron表达式
     * @param description    任务描述
     * @return
     */
    public Boolean addJob(String jobName, String cronExpression, Class cls, String description, JobDataMap jobDataMap) {
        if (!CronExpression.isValidExpression(cronExpression)) {
            return false;
        }

        JobBuilder jobBuilder = JobBuilder.newJob(cls).withIdentity(jobName, JOB_GROUP_NAME)
                .withDescription(description);
        if (jobDataMap != null) {
            jobBuilder.setJobData(jobDataMap);
        }
        // 构建job信息
        JobDetail jobDetail = jobBuilder.build();

        // 表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

        // 按照cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, JOB_GROUP_NAME)
                .startNow().withSchedule(scheduleBuilder).build();

        try {
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            log.error("创建任务失败,失败原因:{}", ExceptionUtils.getStackTrace(e));
            return false;
        }
        return true;
    }

    /**
     * 删除任务
     *
     * @param jobName      任务名称
     * @param jobGroupName 任务组名称
     * @return
     */
    public Boolean deleteJob(String jobName, String jobGroupName) {
        JobKey jobKey = new JobKey(jobName, jobGroupName);
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
        JobDetail jobDetail = null;
        try {
            jobDetail = scheduler.getJobDetail(jobKey);
        } catch (SchedulerException e) {
            log.error("删除{}-任务失败,失败原因:{}", jobName, ExceptionUtils.getStackTrace(e));
            return false;
        }
        try {
            if (jobDetail != null && scheduler.checkExists(jobKey)) {
                scheduler.pauseTrigger(triggerKey);
                scheduler.unscheduleJob(triggerKey);
                scheduler.deleteJob(jobKey);
            }
        } catch (Exception e) {
            log.error("删除{}-任务失败,失败原因:{}", jobName, ExceptionUtils.getStackTrace(e));
            return false;
        }
        return true;
    }

    /**
     * 删除任务
     *
     * @param jobName 任务名称
     * @return
     */
    public Boolean deleteJob(String jobName) {
        JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME);
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, JOB_GROUP_NAME);
        JobDetail jobDetail = null;
        try {
            jobDetail = scheduler.getJobDetail(jobKey);
        } catch (SchedulerException e) {
            log.error("删除{}-任务失败,失败原因:{}", jobName, ExceptionUtils.getStackTrace(e));
            return false;
        }
        try {
            if (jobDetail != null && scheduler.checkExists(jobKey)) {
                scheduler.pauseTrigger(triggerKey);
                scheduler.unscheduleJob(triggerKey);
                scheduler.deleteJob(jobKey);
            }
        } catch (Exception e) {
            log.error("删除{}-任务失败,失败原因:{}", jobName, ExceptionUtils.getStackTrace(e));
            return false;
        }
        return true;
    }

    /**
     * 恢复任务
     *
     * @param jobName      任务名称
     * @param jobGroupName 任务组名称
     * @return
     */
    public boolean resumeJob(String jobName, String jobGroupName) {
        JobKey jobKey = new JobKey(jobName, jobGroupName);
        JobDetail jobDetail = null;
        try {
            jobDetail = scheduler.getJobDetail(jobKey);
        } catch (SchedulerException e) {
            log.error("恢复{}-任务失败,失败原因:{}", jobName, ExceptionUtils.getStackTrace(e));
            return false;
        }
        if (jobDetail != null) {
            try {
                scheduler.resumeJob(jobKey);
            } catch (SchedulerException e) {
                log.error("恢复{}-任务失败,失败原因:{}", jobName, ExceptionUtils.getStackTrace(e));
                return false;
            }
        }
        return true;
    }

    /**
     * 恢复任务
     *
     * @param jobName 任务名称
     * @return
     */
    public boolean resumeJob(String jobName) {
        JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME);
        JobDetail jobDetail = null;
        try {
            jobDetail = scheduler.getJobDetail(jobKey);
        } catch (SchedulerException e) {
            log.error("恢复{}-任务失败,失败原因:{}", jobName, ExceptionUtils.getStackTrace(e));
            return false;
        }
        if (jobDetail != null) {
            try {
                scheduler.resumeJob(jobKey);
            } catch (SchedulerException e) {
                log.error("恢复{}-任务失败,失败原因:{}", jobName, ExceptionUtils.getStackTrace(e));
                return false;
            }
        }
        return true;
    }

    /**
     * 暂停任务
     *
     * @param jobName      任务名称
     * @param jobGroupName 任务组名称
     * @return
     */
    public boolean pauseJob(String jobName, String jobGroupName) {
        JobKey jobKey = new JobKey(jobName, jobGroupName);
        JobDetail jobDetail = null;

        try {
            jobDetail = scheduler.getJobDetail(jobKey);
        } catch (SchedulerException e) {
            log.error("暂停任务失败,失败原因:{}", ExceptionUtils.getStackTrace(e));
            return false;
        }

        if (jobDetail != null) {
            try {
                scheduler.pauseJob(jobKey);
            } catch (SchedulerException e) {
                log.error("暂停任务失败,失败原因:{}", ExceptionUtils.getStackTrace(e));
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }

    /**
     * 暂停任务
     *
     * @param jobName 任务名称
     * @return
     */
    public boolean pauseJob(String jobName) {
        JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME);
        JobDetail jobDetail = null;

        try {
            jobDetail = scheduler.getJobDetail(jobKey);
        } catch (SchedulerException e) {
            log.error("暂停任务失败,失败原因:{}", ExceptionUtils.getStackTrace(e));
            return false;
        }

        if (jobDetail != null) {
            try {
                scheduler.pauseJob(jobKey);
            } catch (SchedulerException e) {
                log.error("暂停任务失败,失败原因:{}", ExceptionUtils.getStackTrace(e));
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }

    /**
     * 恢复所有任务
     *
     * @return
     */
    public boolean resumeAllJob() {
        try {
            scheduler.resumeAll();
            return true;
        } catch (SchedulerException e) {
            log.error("恢复所有任务失败,失败原因:{}", ExceptionUtils.getStackTrace(e));
            return false;
        }
    }
}
